package middlewareWeb;

import java.util.*;
import java.net.*;
import java.util.Collections.*;

/**
 * Classe che implementa il Manager del middleware
 * @author myusy
 * @version 1.0
 */
public class Manager {
    private Integer num_activity_inserite;
    private Vector<Activity> activities;
    private String id;// Id componente univoco
    private Integer num_sequenza_operazione;//contatore del numero di operazioni
    private Hashtable clocks = new Hashtable();

    /**
     * Metodo costruttore dell'oggetto Manager
     */
    public Manager(){
        this.num_sequenza_operazione = 0;
        this.num_activity_inserite=0;
        initClocks();
    }

    /**
     * Metodo costruttore dell'oggetto Manager
     * @param id ID univoco associato al componente
     */
    public Manager(String id){
        this.id = id;
        this.num_sequenza_operazione = 0;
        this.num_activity_inserite=0;
        initClocks();
    }

    /**
     * metodo che inizializza il vector clock locale del manager
     */
    private void initClocks()
    {
        clocks.put("M001",new Integer(0));
        clocks.put("W001",new Integer(0));
        clocks.put("W002",new Integer(0));
        clocks.put("W003",new Integer(0));
        clocks.put("T001",new Integer(0));
        clocks.put("F001",new Integer(0));
    }

    /**
     * Metodo che restituisce l'identificativo
     * @return ID univoco del Manager
     */
    public String getId(){
        return id;
    }

    /**
     * Metodo che implementa il contatore delle operazioni effettuate
     */
    public void IncrementaSequenzaOperazione(){
        this.num_sequenza_operazione ++;
    }

    /**
     * Metodo che restituisce il numero di sequenza operazione
     * @return numero di operazioni finora effettuate dal componente
     */
    public Integer getSequenzaOperazione(){
        return this.num_sequenza_operazione;
    }

    /**
     * Metodo che incrementa il valore del contatore che conta il numero di activity inserite
     * @return numero di activity inserite nel Manager
     */
    public Integer IncrementaActivityInserite(){
        this.num_activity_inserite ++;
        return this.num_activity_inserite;
    }

    /**
     * Metodo che restituisce il timestamp()
     * @return una stringa che racchiude il contenuto del vector clock
     */
        public String getTimestamp()
    {
        return clocks.toString();
    }

     /**
     * Metodo che incrementa il valore del clock del componente
     * @return una stringa che racchiude il contenuto del vector clock
     */
        public String IncrementaClock(){
        int a= ((Integer)this.clocks.get(this.id)).intValue();
        a++;
        this.clocks.put(this.id,new  Integer(a));
        return clocks.toString();
    }

    /**
     * Metodo principale del manager che si occupa di eseguire le activities
     */
    public void run(){
        this.getActivities().firstElement().scheduleActivity();
    }

    /**
     * Metodo che consente di ottenere le attività da eseguire
     * @return Vactor di oggetti Activity
     */
    public Vector<Activity> getActivities()
    {
        return activities;
    }

    /**
     * Metodo che consente di settare l'elenco delle attività
     * @param acts Vector delle attività
     */
    public void setActivities(Vector<Activity> acts)
    {
        activities = acts;
    }

    public static void main(String[] args) {

        System.out.println("Manager avviato");
        TaskDescriptor td1 = new TaskDescriptor(1,TaskTYPE.Executable,"tipo comando","/home/myusy/Scrivania/Raul.jpg");
        TaskDescriptor td2 = new TaskDescriptor(2,TaskTYPE.scriptBash,"tipo comando","/home/myusy/Scrivania/Raul1.jpg");
        TaskDescriptor td3 = new TaskDescriptor(3,TaskTYPE.Literals,"tipo comando","/home/myusy/Scrivania/Raul2.jpg");
        Vector<TaskDescriptor> td_vector = new Vector<TaskDescriptor>();
        td_vector.add(td1);
        td_vector.add(td2);
        td_vector.add(td3);

        Workflow wf = new Workflow(1,td_vector);

        Address a1 = new Address(5000,"127.0.0.1");
        Address a2 = new Address(5001,"127.0.0.1");
        Address a3 = new Address(5002,"127.0.0.1");
        Vector<Address> a_vector = new Vector<Address>();
        a_vector.add(a1);
        a_vector.add(a2);
        a_vector.add(a3);

        WorkerNetwork wn = new WorkerNetwork(a_vector);

        Activity act = new Activity(wf,wn,new TQueueManagerProxy());
        Vector<Activity> act_vector = new Vector<Activity>();
        act_vector.add(act);
        Manager man = new Manager("M001");
        man.setActivities(act_vector);
        man.IncrementaActivityInserite();
        
        try{

            DatagramSocket socketPop = new DatagramSocket(6000);
            System.out.println("ServerPop Manager avviato");
            man.run();
            man.IncrementaSequenzaOperazione();

            /* Scrittura Log */
            LoggerMW logger= new LoggerMW();
            logger.creaLog(man.getId(),man.IncrementaClock(),
                        man.getSequenzaOperazione().toString(),
                        man.getActivities().size(),
                        man.num_activity_inserite.toString(),
                        man.activities.firstElement().getWf().toXML(),
                        "ServerPop Manager avviato");


            while(true){
                byte[] buffer = new byte[512];
                DatagramPacket packetIn = new DatagramPacket(buffer,buffer.length);
                socketPop.receive(packetIn);
                System.out.println("Arrivato richiesta di POP al Manager");
                Thread server_pop = new Thread(new ManagerThreadPop(packetIn));
                server_pop.start();
            }
        }
        catch(Exception e)
        {
            System.out.println("Eccezione: " + e.getMessage());
        }


    }

   }
